#include <vcl.h>
#pragma hdrstop

#define MODULE_TAG 2

#include "uFileOp.h"
#include "Eic.h"
#include "FileCtrl.hpp"
#include <io.h>
#include <Dos.h>
#include "shlobj.h"
#include <ShellAPI.h>
#include <Limits.h>
#include <StdDef.h>
#include <ShlObj.h>
#include <WindowsX.h>

#pragma package(smart_init)
#pragma resource "*.dfm"

int DerniereErreur;

__fastcall TdlgFileOperation::TdlgFileOperation(TComponent* Owner,const AnsiString &Titre,enum TCommonAVI Animation):TForm(Owner)
{
  Top = 20;
  Left = 20;
  Caption = Titre;
  aAnimation->CommonAVI = Animation;
  aAnimation->Active = true;
}




/*
  Cette fonction détruit un répertoire.
*/
bool __fastcall DelRepertoire(const AnsiString &Repertoire, bool bIgnorerMessageErreur)
{
  int Attibuts = faAnyFile;
  TdlgFileOperation *dlgFileOperation = 0;
  TStringList *ListeRep = 0;
  TSearchRec ParametresDuFichier;
  AnsiString Extension;
  try
    {
      DerniereErreur = efAucuneErreur;
      ListeRep = new TStringList();
      dlgFileOperation = new TdlgFileOperation(0,"Supprimer...",aviDeleteFile);
      dlgFileOperation->Show();
      dlgFileOperation->Barre->Max = EicFileNumber(Repertoire);
      dlgFileOperation->Barre->Position = 0;
      if (!FindFirst(Repertoire + "\\*.*",Attibuts,ParametresDuFichier))
        {//On a trouvé un premier fichier
          do
            {
              if ((ParametresDuFichier.Name != ".") && (ParametresDuFichier.Name != ".."))
                {//On va pas détruire les répertoires "." et ".."
                  if (ParametresDuFichier.Attr & faDirectory)
                    ListeRep->Add(ParametresDuFichier.Name);         //Il y a des sous-répertoires qu'on détruira plus tard
                  else
                    {
                      dlgFileOperation->Texte = ParametresDuFichier.Name;
                      AnsiString asNomFichier = Repertoire + "\\" + ParametresDuFichier.Name;
                      if (_access(asNomFichier.c_str(),06) == 0)
                        if (!EicFileDirDelete(asNomFichier))
                         {
                            DerniereErreur = efImpossibleDeSupprimerLeFichier;
                            if (!bIgnorerMessageErreur)
                              {
                                AfficheLastError();
                                goto FinDelRepertoire;
                              }
                          }
                    }
                }
              dlgFileOperation->Barre->Position++;
            }
          while (!FindNext(ParametresDuFichier));
        }
      FindClose(ParametresDuFichier);
      for (int i = 0;i < ListeRep->Count;i++)
        {//Il reste des sous-répertoires à détruire
          DelRepertoire(Repertoire + "\\" + ListeRep->Strings[i], bIgnorerMessageErreur);
        }
      HANDLE hFile = CreateFile(Repertoire.c_str(),GENERIC_READ | GENERIC_WRITE,FILE_SHARE_READ | FILE_SHARE_WRITE,0,OPEN_EXISTING,FILE_FLAG_BACKUP_SEMANTICS,0);
      CloseHandle(hFile);
      if (!::RemoveDirectory(Repertoire.c_str()))
        {
          SetFileAttributes(Repertoire.c_str(),FILE_ATTRIBUTE_NORMAL);   //Peut-être le répertoire était en lecture seule
          if (!::RemoveDirectory(Repertoire.c_str()))
            {
              DerniereErreur = efImpossibleDeSupprimerLeRepertoire;
              if (!bIgnorerMessageErreur)
                {
                AfficheLastError();
                goto FinDelRepertoire;
                }
            }
        }
    }
  catch (...)
    {
       DerniereErreur = efImpossibleDeSupprimerLeRepertoire;
       if (!bIgnorerMessageErreur)
        AfficheLastError();
    }
  FinDelRepertoire:
  FindClose(ParametresDuFichier);
  if (dlgFileOperation)
    dlgFileOperation->Close();
  delete dlgFileOperation;
  delete ListeRep;
  return (DerniereErreur == efAucuneErreur);
}




/*
  Cette fonction détruit un fichier ou un répertoire.
*/
bool __fastcall EicFileDirDelete(const AnsiString &Fic_Rep, bool bIgnorerMessageErreur)
{
  AnsiString FicRep = ExcludeTrailingBackslash(Fic_Rep);
  DerniereErreur = efErreurInconnue;
  if (FileExists(FicRep))
    {
      try
        {
          if (::DeleteFile(FicRep.c_str()))          //On supprime le fichier
            {
              DerniereErreur = efAucuneErreur;
              return true;
            }
          SetFileAttributes(FicRep.c_str(),FILE_ATTRIBUTE_NORMAL);   //Peut-être le fichier était en lecture seule
          if(::DeleteFile(FicRep.c_str()))          //On supprime le fichier
            {
              DerniereErreur = efAucuneErreur;
              return true;
            }
        }
      catch (Exception &e)
        {
          if (!bIgnorerMessageErreur)
          {
            AfficheLastError();
            EICDisplayException(TAG(__LINE__),e);
          }
        }
      DerniereErreur = efImpossibleDeSupprimerLeFichier;
      return false;
    }
  if (DirectoryExists(FicRep))
      return DelRepertoire(FicRep, bIgnorerMessageErreur);
  else
    {
      DerniereErreur = efAucuneErreur;
      return true;
    }
}




/*
  Cette fonction copie un répertoire.
*/
bool __fastcall CopyRepertoire(const AnsiString &RepSource,const AnsiString &RepDestination,TStringList *ListeExtension)
{
  bool Ok = true;
  int Attibuts = faAnyFile;
  TStringList *ListeRep = 0;
  TdlgFileOperation *dlgFileOperation = 0;
  TSearchRec ParametresDuFichier;
  AnsiString Extension;
  try
    {
      DerniereErreur = efErreurInconnue;
      ListeRep = new TStringList();
      dlgFileOperation = new TdlgFileOperation(0,"Copier...",aviCopyFile);
      dlgFileOperation->Show();
      dlgFileOperation->Barre->Max = EicFileNumber(RepSource);
      dlgFileOperation->Barre->Position = 0;
      if (!DirectoryExists(RepDestination))
        if (!CreateDirectory(RepDestination.c_str(),0))
          {
            AfficheLastError();
            DerniereErreur = efImpossibleDeCreerLeRepertoire;
            goto FinCopyRepertoire;
          }
      if (!FindFirst(RepSource + "\\*.*",Attibuts,ParametresDuFichier))
        {//On a trouvé un premier fichier
          do
            {
              if ((ParametresDuFichier.Name != ".") && (ParametresDuFichier.Name != ".."))
                {//On ne va pas copier les répertoire "." et ".."
                  if (ParametresDuFichier.Attr & faDirectory)
                    ListeRep->Add(ParametresDuFichier.Name);         //Il y a des sous-répertoires qu'on copiera plus tard
                  else
                    {
                      if (ListeExtension)
                        {
                          Extension = ExtractFileExt(ParametresDuFichier.Name);
                          if (!Extension.IsEmpty())
                            Extension.Delete(1,1);
                          Ok = (ListeExtension->IndexOf(Extension) >= 0);
                        }
                      if (Ok)
                        {
                          dlgFileOperation->Texte = ParametresDuFichier.Name;
                          if (EICCopy(RepSource + "\\" + ParametresDuFichier.Name,RepDestination + "\\" + ParametresDuFichier.Name,CF_DEFAULT) != CF_ERR_OK)
                            {
                              AfficheLastError();
                              DerniereErreur = efImpossibleDeCreerLeRepertoire;
                              goto FinCopyRepertoire;
                            }
                        }
                    }
                }
              dlgFileOperation->Barre->Position++;
            }
          while (!FindNext(ParametresDuFichier));
        }
      for (int i = 0;i < ListeRep->Count;i++)
        {//Il reste des sous-répertoires à copier
          CopyRepertoire(RepSource + "\\" + ListeRep->Strings[i],RepDestination + "\\" + ListeRep->Strings[i],ListeExtension);
        }
      DerniereErreur = efAucuneErreur;
    }
  catch (...)
    {
      AfficheLastError();
    }
  FinCopyRepertoire:
  FindClose(ParametresDuFichier);
  if (dlgFileOperation)
    dlgFileOperation->Close();
  delete dlgFileOperation;
  delete ListeRep;
  return (DerniereErreur == efAucuneErreur);
}




bool __fastcall EicFileDirCopy(const AnsiString &Fic_RepSource,const AnsiString &Fic_RepDestination,const AnsiString &ListeExtension)
{
  TStringList *Liste = 0;
  bool Resultat = false;
  try
    {
      Liste = new TStringList();
      Liste->CommaText = ListeExtension;
      Resultat = EicFileDirCopy(Fic_RepSource,Fic_RepDestination,Liste);
    }
  catch (Exception &e)
    {
      EICDisplayException(TAGL,e);
    }
  delete Liste;
  return Resultat;
}



/*
  Cette fonction copie un répertoire ou un fichier.
*/
bool __fastcall EicFileDirCopy(const AnsiString &Fic_RepSource,const AnsiString &Fic_RepDestination,TStringList *ListeExtension)
{
  AnsiString FicRepSource,FicRepDestination;
  try
    {
      DerniereErreur = efErreurInconnue;
      FicRepSource = ExcludeTrailingBackslash(Fic_RepSource);
      FicRepDestination = ExcludeTrailingBackslash(Fic_RepDestination);
      if (FileExists(FicRepSource))
        {
          if (EICCopy(FicRepSource,FicRepDestination,CF_NO_OVERWRITE) == CF_ERR_OK)
            {
              DerniereErreur = efAucuneErreur;
              return true;
            }
          AfficheLastError();
          DerniereErreur = efImpossibleDeCopierLeFichier;
          return false;
        }
      else
        {
          if (DirectoryExists(FicRepSource))
            return CopyRepertoire(FicRepSource,FicRepDestination,ListeExtension);
          else
            {
    //          AfficheLastError();
              DerniereErreur = efRepertoireInexistant;
              return false;
            }
        }
    }
  catch (Exception &e)
    {
    }
  return false;
}




/*
  Cette fonction renomme un répertoire ou un fichier.
*/
bool __fastcall EicFileDirRename(const AnsiString &Fic_RepSource,const AnsiString &Fic_RepDestination)
{
  AnsiString FicRepSource,FicRepDestination;
  TdlgFileOperation *dlgFileOperation = 0;
  try
    {
      DerniereErreur = efErreurInconnue;
      FicRepSource = ExcludeTrailingBackslash(Fic_RepSource);
      FicRepDestination = ExcludeTrailingBackslash(Fic_RepDestination);
      if (DirectoryExists(FicRepSource))
        {//On renomme un répertoire
          dlgFileOperation = new TdlgFileOperation(0,"Renommer...",aviCopyFiles);
          dlgFileOperation->Show();
          dlgFileOperation->Texte = ExtractFileName(FicRepSource) + " => " + ExtractFileName(FicRepDestination);
          if(!::MoveFileEx(FicRepSource.c_str(),FicRepDestination.c_str(),MOVEFILE_WRITE_THROUGH))
            {
              AfficheLastError();
              DerniereErreur = efImpossibleDeRenommerLeFichier;
            }
        }
      else
        {
          if (!::MoveFileEx(FicRepSource.c_str(),FicRepDestination.c_str(),MOVEFILE_WRITE_THROUGH))
            {
              AfficheLastError();
              DerniereErreur = efImpossibleDeRenommerLeRepertoire;
            }
        }
      DerniereErreur = efAucuneErreur;
    }
  catch(...)
    {
      AfficheLastError();
    }
  delete dlgFileOperation;
  dlgFileOperation = 0;
  return (DerniereErreur == efAucuneErreur);
}




/*
  Cette fonction donne le nombre de fichiers dans un répertoire.
*/
int __fastcall EicFileNumber(const AnsiString &Repertoire,bool Recursif)
{
  int Attibuts = faAnyFile,Nb = 0;
  TStringList *ListeRep = 0;
  TSearchRec ParametresDuFichier;
  try
    {
      if (Recursif)
        ListeRep = new TStringList();
      if (!FindFirst(Repertoire + "\\*.*",Attibuts,ParametresDuFichier))
        {//On a trouvé un premier fichier
          do
            {
              if (ParametresDuFichier.Attr & faDirectory)
                {//Il y a des sous-répertoires qu'on comptera plus tard
                  if (Recursif && (ParametresDuFichier.Name != ".") && (ParametresDuFichier.Name != ".."))   //On fait attention de ne pas effacer tout le disque
                    ListeRep->Add(ParametresDuFichier.Name);
                }
              else
                Nb++;
            }
          while (!FindNext(ParametresDuFichier));
          if (Recursif)
            for (int i = 0;i < ListeRep->Count;i++)
              {//Il reste des sous-répertoires à compter
                Nb += EicFileNumber(Repertoire + "\\" + ListeRep->Strings[i],Recursif);
              }
        }
    }
  catch (...)
    {
      AfficheLastError();
      Nb = 0;
    }
  FindClose(ParametresDuFichier);
  if (Recursif)
    delete ListeRep;
  return Nb;
}




bool __fastcall EicMoveFiles(const AnsiString &RepertoireSource,const AnsiString &RepertoireDestination)
{
  // Voir eic.h pour les explications
  if( _MoveFile) {
    DerniereErreur = efImpossibleDeDeplacerLesFichiers;
    try {
      if( ::MoveFileEx( RepertoireSource.c_str(), RepertoireDestination.c_str(), MOVEFILE_WRITE_THROUGH)!=0);
        {
          DerniereErreur = efAucuneErreur;
          return true;
        }
    } catch( ...) {
      AfficheLastError();
    }
    return false;
  }
  // --------------------------------

  bool Ok = true;
  TdlgFileOperation *dlgFileOperation = 0;
  int Attibuts = faAnyFile;
  TSearchRec ParametresDuFichier;
  try
    {
      DerniereErreur = efImpossibleDeDeplacerLesFichiers;
      dlgFileOperation = new TdlgFileOperation(0,"Déplacer...",aviCopyFiles);
      dlgFileOperation->Show();
      dlgFileOperation->Barre->Max = EicFileNumber(RepertoireSource);
      dlgFileOperation->Barre->Position = 0;
      if (!DirectoryExists(RepertoireDestination))
        ForceDirectories(RepertoireDestination); //Répertoire destination inexistant, on le force
      if (!FindFirst(RepertoireSource + "\\*.*",Attibuts,ParametresDuFichier))
        {//On a trouvé un premier fichier
          do
            {
              if ((ParametresDuFichier.Name != ".") && (ParametresDuFichier.Name != ".."))
                {//On bouge le fichier
                  dlgFileOperation->Texte = ParametresDuFichier.Name;
                  if (!MoveFileEx((RepertoireSource + "\\" + ParametresDuFichier.Name).c_str(),(RepertoireDestination + "\\" + ParametresDuFichier.Name).c_str(), MOVEFILE_WRITE_THROUGH))
                    {
                      Ok = false;
                      break;                     //On n'arrive pas à bouger le fichier
                    }
                  dlgFileOperation->Barre->Position++;
                }
            }
          while (!FindNext(ParametresDuFichier));
        }
      if (Ok)
        DerniereErreur = efAucuneErreur;
    }
  catch (...)
    {
      AfficheLastError();
    }
  FindClose(ParametresDuFichier);
  delete dlgFileOperation;
  return (DerniereErreur == efAucuneErreur);
}




bool __fastcall EicDirDeleteContenu(const AnsiString &aRepertoire,TStringList *ListeSaufLesFichiersContenant, bool bIgnorerMessageErreur)
{
  bool Resultat = false,Sauf;
  TdlgFileOperation *dlgFileOperation = 0;
  int Attibuts = faAnyFile;
  TSearchRec ParametresDuFichier;
  AnsiString _aRepertoire(ExcludeTrailingBackslash(aRepertoire));
  try
    {
      DerniereErreur = efErreurInconnue;
      dlgFileOperation = new TdlgFileOperation(0,"Supprimer...",aviDeleteFile);
      dlgFileOperation->Show();
      dlgFileOperation->Barre->Max = EicFileNumber(_aRepertoire);
      dlgFileOperation->Barre->Position = 0;
      if (!FindFirst(_aRepertoire + "\\*.*",Attibuts,ParametresDuFichier))
        {//On a trouvé un premier fichier
          do
            {
              if ((ParametresDuFichier.Name != ".") && (ParametresDuFichier.Name != ".."))
                {//On va peut-être supprimer le fichier
                  if (ListeSaufLesFichiersContenant)
                    {
                      Sauf = false;
                      for (int i = 0;i < ListeSaufLesFichiersContenant->Count;i++)
                        if (ParametresDuFichier.Name.UpperCase().Pos(ListeSaufLesFichiersContenant->Strings[i].UpperCase()))
                          {
                            Sauf = true;         //On ne supprime pas le fichier
                            break;
                          }
                      if (Sauf)
                        continue;
                    }
                  dlgFileOperation->Texte = ParametresDuFichier.Name;
                  if (!EicFileDirDelete(_aRepertoire + "\\" + ParametresDuFichier.Name, bIgnorerMessageErreur))
                    {
                      Resultat = true;           //Bidouille pour renvoyer false

                      if (!bIgnorerMessageErreur)
                         {
                         AfficheLastError();
                         break;                     //On n'arrive pas à Supprimer le fichier
                         }
                    }
                  dlgFileOperation->Barre->Position++;
                }
            }
          while (!FindNext(ParametresDuFichier));
        }
      Resultat = !Resultat;
      if (Resultat)
        DerniereErreur = efAucuneErreur;
      else
        ASSERT(bIgnorerMessageErreur || DerniereErreur != efAucuneErreur);  //EicFileDirDelete a dû placer la bonne erreur
    }
  catch (...)
    {
      if (!bIgnorerMessageErreur)
        AfficheLastError();
    }
  FindClose(ParametresDuFichier);
  delete dlgFileOperation;
  return Resultat;
}



